// Copyright (C) 2006 Taylor L. Riché <riche@cs.utexas.edu>
//  
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software 
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//

#ifndef TCP_PACKET_HH
#define TCP_PACKET_HH

#include <netinet/tcp.h>

#include "IP_Packet.hh"

namespace pktTypes {

const unsigned int TCP_HSIZE = 0x14; // 20

  class TCP_Packet : public IP_Packet
{
protected:
  tcphdr * tcpHdr;
  payload_t tcp_payload;
  uint16_t tcpLength;
public:
  TCP_Packet() : tcpHdr(NULL), tcp_payload(NULL) {}
  TCP_Packet(const IP_Packet & ipPkt) : IP_Packet(ipPkt)
  {
    assert(payload != NULL);
    tcpHdr = (tcphdr *)ip_payload;
    tcp_payload = ((payload_t)tcpHdr) + TCP_HSIZE;
    tcpLength = ipLength - IPv4_HSIZE;
  }
  virtual ~TCP_Packet() {}
  virtual int chksum();
  
  inline void setSrcPort(uint16_t sp) {tcpHdr->source = htons(sp);}
  inline uint16_t getSrcPort() {return ntohs(tcpHdr->source);}
  inline void setDstPort(uint16_t dp) {tcpHdr->dest = htons(dp);}
  inline uint16_t getDstPort() {return ntohs(tcpHdr->dest);}
  inline void setSeqNum(uint32_t sn) {tcpHdr->seq = htonl(sn);}
  inline uint32_t getSeqNum() {return ntohl(tcpHdr->seq);}
  inline void setAckSeqNum(uint32_t asn) {tcpHdr->ack_seq = htonl(asn);}
  inline uint32_t getAckSeqNum() {return ntohl(tcpHdr->ack_seq);}
  inline void setDataOff(uint8_t dof) {tcpHdr->doff = dof;}
  inline uint8_t getDataOff() {return tcpHdr->doff;}
  inline void setFin(bool f) {tcpHdr->fin = f?1:0;}
  inline bool getFin() {return tcpHdr->fin;}
  inline void setSyn(bool s) {tcpHdr->syn = s?1:0;}
  inline bool getSyn() {return tcpHdr->syn;}
  inline void setRst(bool r) {tcpHdr->rst = r?1:0;}
  inline bool getRst() {return tcpHdr->rst;}
  inline void setPsh(bool p) {tcpHdr->psh = p?1:0;}
  inline bool getPsh() {return tcpHdr->psh;}
  inline void setAck(bool a) {tcpHdr->ack = a?1:0;}
  inline bool getAck() {return tcpHdr->ack;}
  inline void setUrg(bool u) {tcpHdr->urg = u?1:0;}
  inline bool getUrg() {return tcpHdr->urg;}
  inline void setWindow(uint16_t w) {tcpHdr->window = htons(w);}
  inline uint16_t getWindow() {return ntohs(tcpHdr->window);}
  inline void setCheck(uint16_t c) {tcpHdr->check = htons(c);}
  inline uint16_t getCheck() {return ntohs(tcpHdr->check);}
  inline void setUrgPtr(uint16_t u) {tcpHdr->urg_ptr = htons(u);}
  inline uint16_t getUrgPtr() {return ntohs(tcpHdr->urg_ptr);}
  inline payload_t getPayload() {return tcp_payload;}
  inline uint16_t getRes2() {return ntohs(tcpHdr->res2);}
  inline void setRes2(uint16_t val) {tcpHdr->res2 = htons(val);}
};

}

#endif // TCP_PACKET_HH
